package ar.edu.unicen.exa.isistan.archassis.ia.api.db;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;

import ar.edu.unicen.exa.isistan.archassis.ia.seed.ExtendsSeed;
import ar.edu.unicen.exa.isistan.archassis.ia.seed.ISeed;
import ar.edu.unicen.exa.isistan.archassis.ia.seed.ImplementsSeed;
import ar.edu.unicen.exa.isistan.archassis.ia.seed.MetodoSeed;
import ar.edu.unicen.exa.isistan.archassis.ia.seed.VariableSeed;

public class JavaClass implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public static final String DEFAULT_EXTENDS = "java.lang.Object";
	
	public static final String RN_IMPLEMENTS = "Implementa";

	public static final String RU_EXTENDS = "Extiende";
	
	public static final String RU_RUNS = "Ejecuta";

	private ExtendsSeed entiende;

	private List<ImplementsSeed> implementa;

	private List<VariableSeed> variables;
	
	private List<MetodoSeed> metodos;

	private float peso = 1;

	private String nombre;
	
	
	public JavaClass() {
		metodos = new ArrayList<MetodoSeed>();
	}
	public List<MetodoSeed> getMetodos() {
		return metodos;
	}

	public void setMetodos(List<MetodoSeed> metodos) {
		if (metodos == null) {
			this.metodos = new ArrayList<MetodoSeed>();
		} else {
			this.metodos = metodos;
		}
		fillMetodoSeedClassOwner();
	}
	private void fillMetodoSeedClassOwner() {
		if (this.metodos == null) return;
//		for (MetodoSeed metodoSeed: metodos) {
//			metodoSeed.setJavaClass(this);
//		}
	}

	public String getEntiende() {
		if(entiende == null){
			return DEFAULT_EXTENDS;
		}
		return entiende.getValor();
	}
	
	public ExtendsSeed getEntiendeSeed() {
		return entiende;
	}

	public List<ImplementsSeed> getImplementa() {
		return implementa;
	}

	public void setImplementa(List<ImplementsSeed> implementa) {
		this.implementa = implementa;
	}

	public List<VariableSeed> getVariables() {
		return variables;
	}

	public void setVariables(List<VariableSeed> variables) {
		this.variables = variables;
	}

	public float getPeso() {
		return peso;
	}

	public void setPeso(float peso) {
		this.peso = peso;
	}

	public String getNombre() {
		return nombre;
	}

	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	public void setEntiende(ExtendsSeed entiende) {
		this.entiende = entiende;
	}

	public void setListImplement(List<String> implementas) {
		List<ImplementsSeed> listaImplements = new ArrayList<ImplementsSeed>();
		for (String implemet : implementas) {
			ImplementsSeed impl = new ImplementsSeed(implemet);
			listaImplements.add(impl);
		}
		this.implementa = listaImplements;
	}

	public JavaClass(String name, String ruExtends, List<String> rnImplements) {

		this.nombre = name;
		this.entiende = new ExtendsSeed(ruExtends);
		this.setListImplement(rnImplements);
	}

	public float eval(JavaClass c) {
		// Inicializo con el extiende
		float result = entiende.eval(c);
		// Comienza en 1 porque ya se evaluo extiende
		float size = 0f;
		float resultMedium = 0;
		
		for (ImplementsSeed impSemilla : this.implementa) {
			resultMedium += impSemilla.eval(c);
			size ++;
		}
		if(size > 0)
			result = (result + (resultMedium / size)) / 2f;
		resultMedium = 0;
		size = 0;

		for (VariableSeed variable : this.variables) {
			resultMedium += (variable.eval(c));
			size ++;
		}
		
		
		JButton b = new JButton();
		
		if(size > 0)
			result = (result + (resultMedium / size)) / 2f;
		resultMedium = 0;
		size = 0;
		
		if (this.metodos != null){
			for (MetodoSeed metodo : this.metodos) {
				resultMedium += (metodo.eval(c));
				size ++;
			}
		}
		if(size > 0)			
			result = (result + (resultMedium / size)) / 2f;

		return result;

	}

	public List<ISeed> getAllSeed() {
		List<ISeed> all = new ArrayList<ISeed>();
		if (this.entiende != null)
			all.add(this.entiende);
		if (this.implementa != null)
			all.addAll(this.implementa);
		if (this.variables != null)
			all.addAll(this.variables);
		if (this.metodos != null)
			all.addAll(this.metodos);
		return all;
	}
	
	public void actualizarPesosSemillas(JavaClass c) {
		// Inicializo con el extiende
		entiende.updatePeso(c);
		for (ImplementsSeed impSemilla : this.implementa) {
			impSemilla.updatePeso(c);
		}

		for (VariableSeed variable : this.variables) {
			variable.updatePeso(c);
		}
		for (MetodoSeed metodo : this.metodos) {
			metodo.updatePeso(c);
		}
	}
	public float getMaxPesoSemilla(){
		float result = 0;
		
		
		for (ISeed seed : this.getAllSeed()) {
			if (seed.getPeso() > result){
				result = seed.getPeso();
			}
		}
		return result;
	}

	private String srcFolder;
	public void setSRCFolder(String relPath) {
		this.srcFolder = relPath;
	}
	public String getSRCFolder() {
		return this.srcFolder;
	}

}
